home *** CD-ROM | disk | FTP | other *** search
- From: Nico Josuttis <nico@bredex.de>
- Message-ID: <199604191427.QAA11829@bredex.bredex.de>
- X-Original-Date: Fri, 19 Apr 1996 16:27:09 +0200
- Path: in2.uu.net!bounce-back
- Date: 19 Apr 96 14:54:19 GMT
- Approved: fjh@cs.mu.oz.au
- Newsgroups: comp.std.c++
- Subject: STL bug with example: remove_if() looses function state
- References: <199604110827.KAA02243@bredex.bredex.de>
- Reply-To: nico@bredex.de
- Organization: Bredex GmbH
- Keywords: STL
- Apparently-To: nico@bredex.de
- Apparently-To: std-c++@ncar.ucar.edu
- X-Auth: PGPMoose V1.1 PGP comp.std.c++
- iQBEAgUBMXepOuEDnX0m9pzZAQHFcgF4gf/i3i0mE5lSWX3B07Dh5RTFCr5nn60h
- 6/nUjwzWhh9b7EuHV5PowyIiL5vtVXQ=
- =hP/o
-
- Some people asked for an example of my remove_if() problem.
- Here is the problem with example.
-
- The example uses remove_if() to remove only the first element
- with a given value.
- A function object (that has no side effects)
- is designed to return true only for the first
- element having a given value.
- But using it as parameter of remove_if(), it is
- duplicated and thus does return true twice.
- That results in removing not only the first but also the
- second element. OOOPS
-
- ------------------------- snip -----------
- #include <iostream>
- #include <list>
- #include <algorithm>
- using namespace std;
-
- class FirstElemWithValue {
- private:
- int value;
- bool found;
- public:
- FirstElemWithValue (int v) : value(v), found(false) {
- }
- bool operator() (int elem) {
- // return true only for the first found elem
- if (!found && elem == value) {
- found = true;
- return true;
- }
- return false;
- }
- };
-
- int main ()
- {
- list<int> m;
-
- m.push_back (1);
- m.push_back (2);
- m.push_back (4);
- m.push_back (3);
- m.push_back (5);
- m.push_back (6);
- m.push_back (2);
- m.push_back (0);
- m.push_back (2);
-
- copy (m.begin(), m.end(), ostream_iterator<int>(cout," "));
- cout << endl;
-
- /* remove first element with value 2
- */
- list<int>::iterator pos;
- pos = remove_if (m.begin(), m.end(),
- FirstElemWithValue(2));
- m.erase (pos, m.end());
-
- copy (m.begin(), m.end(), ostream_iterator<int>(cout," "));
- cout << endl;
- }
- ------------------- snip --------------------------
-
- The output is:
- 1 2 4 3 5 6 2 0 2
- 1 4 3 5 6 0 2
- but should be:
- 1 2 4 3 5 6 2 0 2
- 1 4 3 5 6 2 0 2
-
- This happens due to the current implementation of
- remove_if() which calls find_if() and remove_copy_if():
-
- > template <class ForwardIterator, class Predicate>
- > ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
- > Predicate pred) {
- > first = find_if(first, last, pred);
- > ForwardIterator next = first;
- > return first == last ? first : remove_copy_if(++next, last, first, pred);
- > }
-
- So pred() is called with two different copies of
- FirstElemWithValue.
-
- I think it would be better/necessary to disallow such implementations,
- what means to disallow that a function object gets copied before
- calling operator(). At least it should not be allowed that operator()
- is called by different copies of the function object. Otherwise we
- would lose the advantage of function objects in a significant matter.
-
- Am I missing something ?
-
- --
- Nico address: BREDEX GmbH, Nicolai Josuttis
- email: nico@bredex.de Fallersleber-Tor-Wall 23
- phone: +49 531 24330-0 D-38100 Braunschweig
- fax: +49 531 24330-99 Germany
- ---
- [ comp.std.c++ is moderated. To submit articles: try just posting with ]
- [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
- [ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
- [ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
- [ Comments? mailto:std-c++-request@ncar.ucar.edu ]
-